package com.example.baselib.fragment


import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.NonNull
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.viewModelScope
import com.example.baselib.BaseRepository
import com.example.baselib.BaseViewModel
import com.example.baselib.dialog.LoadingDialog
import com.example.baselib.dialog.MsgDialog
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.isActive
import org.jetbrains.annotations.NotNull
import java.lang.Exception

/**
 * A simple [Fragment] subclass.
 */
abstract class BaseFragment<VM : BaseViewModel> : Fragment() {
    protected lateinit var viewModel: VM
    protected val loadingDialog by lazy { LoadingDialog(viewModel) }
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        initVM()
        return setLayoutView(inflater, container)
    }

    override fun onViewCreated(@NonNull view: View,  @NonNull savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initView()
        initData()
        startObserve()
    }
    private fun startObserve() {
        //处理一些通用异常，比如网络超时等
        viewModel.run {
            getError().observe(this@BaseFragment, Observer {
                requestError(it)
            })
            getFinally().observe(this@BaseFragment, Observer {
                requestFinally(it)
            })
        }
    }
    open fun requestFinally(it: Int?) {
        if (loadingDialog.isVisible)
            loadingDialog.dismiss()

    }

    open fun requestError(it: Exception?) {
        //处理一些已知异常
        it?.run {
            when (it) {
                is TimeoutCancellationException -> {
                    MsgDialog("请求超时,请检查网络").show(
                        activity!!.supportFragmentManager,
                        "TimeoutCancellationException"
                    )

                }
                is BaseRepository.RequestException -> {
                    MsgDialog(message.toString()).show(
                        activity!!.supportFragmentManager,
                        "RequestException"
                    )
                }
                is CancellationException -> {
                    MsgDialog("请求取消").show(
                        activity!!.supportFragmentManager,
                        "RequestException"
                    )
                }
                else -> {
                    MsgDialog(message.toString()).show(
                        activity!!.supportFragmentManager,
                        "otherException"
                    )
                }
            }
        }
    }


    private fun initVM() {
        providerVMClass()?.let {
            viewModel = ViewModelProviders.of(this.activity!!).get(it)
            lifecycle.addObserver(viewModel)
        }
        viewModel.setFragmentManager(loadingDialog,activity!!.supportFragmentManager)
    }

    /**
     * @Description: [绑定viewmodel]
     * @Param:
     * @Return:
     */
    protected abstract fun providerVMClass(): Class<VM>?

    private fun setLayoutView(inflater: LayoutInflater, container: ViewGroup?): View? {
        return inflater.inflate(contentLayout(), container, false)
    }

    /**
     * 内容布局
     * @return
     */
    protected abstract fun contentLayout(): Int

    protected abstract fun initView()

    protected abstract fun initData()

    /**
     * 保证同一按钮在1秒内只会响应一次点击事件
     */
    //两次点击按钮之间的间隔，目前为1000ms
    private val MIN_CLICK_DELAY_TIME = 1000
    private var lastClickTime:Long = 0
    fun isFastClick():Boolean {
        var flag = true
        var currentClickTime = System.currentTimeMillis()
        if ((currentClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME ) {
            flag = false
        }
        lastClickTime = currentClickTime;
        return flag
    }
}
